package generator;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.*;
import java.util.HashMap;
import java.util.Properties;


public class SQLGeneratorV2 {

	private HashMap<Class<?>, String> typeMap;

	public SQLGeneratorV2() {
		typeMap = new HashMap<Class<?>, String>();
		loadMappingsFromFile();
	}

	private void loadMappingsFromFile() {
		Properties properties = new Properties();
		try {
			properties.load(new FileInputStream("mapping.properties"));
		} 
		catch (IOException e) {
			e.printStackTrace();
		}

		for(Object key : properties.keySet()) {
			String className = (String) key;

			Class<?> type = handlePrimitiveType(className);

			if(type == null) {
				try {
					type = Class.forName(className);
				} 
				catch (ClassNotFoundException e) {
					System.err.println("Tipo nao encontrado: " +  className);
				}
			}
			
			if(type == null)
				System.err.println("Tipo nao suportado: " + className);
			else
				typeMap.put(type, properties.getProperty(className));
		}
	}

	private Class<?> handlePrimitiveType(String typeName) {
		if(typeName.equals("int"))
			return int.class;
		else if(typeName.equals("double"))
			return double.class;
		//...
		return null;
	}

	private String obtainType(Class<?> type) {
		return typeMap.get(type);
	}

	/**
	 * Gera uma instrucao de SQL para criar uma tabela para uma dada classe 
	 * @param clazz a classe
	 * @return a instrucao CREATE TABLE
	 */
	public String generateCreateTable(Class<?> clazz) {
		StringBuffer sql = new StringBuffer("CREATE TABLE ");
		sql.append(clazz.getSimpleName() + " (");
		Field[] fields = clazz.getDeclaredFields();
		for(int i = 0; i < fields.length; i++) {
			Field f = fields[i];
			Class<?> type = f.getType();
			String name = f.getName();
			if(i != 0)
				sql.append(", ");
			sql.append(name + " " + obtainType(type));
			Annotation ann = f.getAnnotation(PrimaryKey.class);
			if(ann != null)
				sql.append(" PRIMARY KEY");
		}

		sql.append(")");

		return sql.toString();
	}

	/**
	 * Gera uma instrucao de SQL para inserir uma linha 
	 * (coerente com o generateCreateTable)
	 * 
	 * @param object o objecto a inserir
	 * @return a instrucao INSERT
	 */
	public String generateInsert(Object object) {
		StringBuffer sql = new StringBuffer("INSERT INTO ");
		Class<?> clazz = object.getClass();
		sql.append(clazz.getSimpleName());
		sql.append(" (");
		Field[] fields = clazz.getDeclaredFields();
		for(int i = 0; i < fields.length; i++) {
			Field f = fields[i];
			if(i != 0)
				sql.append(", ");
			sql.append(f.getName());
		}
		sql.append(") VALUES (");
		for(int i = 0; i < fields.length; i++) {
			Field f = fields[i];
			f.setAccessible(true);
			Object obj = null;
			try {
				obj = f.get(object);
			} catch (Exception e) {
				e.printStackTrace();
			} 

			if(i != 0)
				sql.append(", ");

			sql.append(convertValue(obj));
		}

		sql.append(")");
		return sql.toString();
	}



	private String convertValue(Object obj) {
		if(obj == null)
			return "NULL";
		else {
			String text = obj.toString();
			if(obj.getClass().equals(String.class)) {
				text = "'" + text + "'";
			}
			return text;
		}
	}
}
